package cn.aresoft.excel.common;

import cn.aresoft.excel.ExcelHandleException;
import cn.aresoft.configuration.ExcelSpringContext;
import cn.aresoft.excel.entity.ExcelDictModel;
import cn.aresoft.excel.entity.ExcelFieldEntity;
import cn.aresoft.excel.entity.ValidateMessage;
import cn.aresoft.excel.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author yangfeng
 * @description:
 * @date 2024/2/2 11:12
 */
public class ImportExcelBase {

    protected Workbook book;
    protected String fileName;


    private static final ExcelFieldConfigUtil excelFieldConfigUtil = ExcelSpringContext.getBean(ExcelFieldConfigUtil.class);
    /**
     * 构造函数
     * @param filePath
     * @param fileName
     * @throws Exception
     */
    protected ImportExcelBase(String filePath, String fileName) throws FileNotFoundException {
        this(fileName, new FileInputStream(filePath + File.separator + fileName));
    }

    /**
     * 构造函数
     * @param fileName    文件名称
     * @param inputStream    文件流
     * @throws Exception
     */
    protected ImportExcelBase(String fileName, InputStream inputStream) {
        try {
            if (fileName.toLowerCase().endsWith("xls")) {
                this.book = new HSSFWorkbook(inputStream);
            } else {
                this.book = new XSSFWorkbook(inputStream);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new ExcelHandleException("文件流读取失败！");
        }
        this.fileName = fileName;
    }



    /**
     * 获得读取的对象集合
     * @return
     * @throws Exception
     */
    public  <T> List<ValidateMessage> getSheetDataList(String sheetName, int startLine, Class<? extends Object> clazz, List<T> objList) {
        Sheet dataSheet = book.getSheet(sheetName);
        if(dataSheet == null){
            throw  new ExcelHandleException("读取数据sheet页不存在！");
        }
       return getSheetDataList(dataSheet,startLine,clazz,objList);
    }

    /**
     * 获得读取的对象集合
     * @return
     * @throws Exception
     */
    protected <T> List<ValidateMessage> getSheetDataList(Sheet dataSheet, int startLine, Class<? extends Object> clazz, List<T> objList) {

        List<ValidateMessage> errorMsgList = new ArrayList<>();
        try {
            Row headRow = dataSheet.getRow(startLine);
            List<ExcelFieldEntity> annotationList = excelFieldConfigUtil.getImportFieldConfig(clazz,headRow);
            startLine++;
            for (int i = startLine; i <= dataSheet.getLastRowNum(); i++) {
                Row dataRow = dataSheet.getRow(i);
                if (dataRow == null || ExcelCellUtil.rowIsEmpty(dataRow, annotationList.size())) {
                    break;
                }
                StringBuffer rowErrorMsg = new StringBuffer();
                T newObj = (T) clazz.newInstance();
                for (int j = 0; j < annotationList.size(); j++) {
                    ExcelFieldEntity excelFieldEntity = annotationList.get(j);
                    Object val = ExcelCellUtil.getCellValue(dataRow, excelFieldEntity.getColumn());
                    if (val != null) {
                        if (excelFieldEntity.getField().getType().equals(String.class)) { //如果类属性是字符串类型
                            if (val instanceof String) {
                                val = val.toString();
                                if (excelFieldEntity.getExcelDictModelList() != null && !excelFieldEntity.getExcelDictModelList().isEmpty()) {
                                    String text = String.valueOf(val);
                                    ExcelDictModel excelDictModel = excelFieldEntity.getExcelDictModelList().stream().filter(dictModel -> dictModel.getText().equals(text)).findFirst().orElse(null);
                                    if (excelDictModel != null) {
                                        val = excelDictModel.getValue();
                                    }
                                } else if (excelFieldEntity.getSelfValueHandler() != null) {
                                    val = excelFieldEntity.getSelfValueHandler().convertTextToValue(val.toString());
                                }
                            } else if(val instanceof Date){
                                val = ExcelUtils.formatDate((Date)val,excelFieldEntity.getPattern());
                            } else {
                                val = val.toString();
                            }
                        } else if (Number.class.isAssignableFrom(excelFieldEntity.getField().getType())) { //如果类属性是数值类型
                            if (!(val instanceof Double)) {
                                rowErrorMsg.append(excelFieldEntity.getTitle()+":要求是数值类型");
                                continue;
                            }
                            if (excelFieldEntity.getField().getType().equals(Integer.class)) {
                                val = ((Double) val).intValue();
                            } else if (excelFieldEntity.getField().getType().equals(Long.class)) {
                                val = ((Double) val).longValue();
                            } else if (excelFieldEntity.getField().getType().equals(Double.class)) {
                                val = ((Double) val);
                            } else if (excelFieldEntity.getField().getType().equals(Float.class)) {
                                val = ((Double) val).floatValue();
                            } else if (excelFieldEntity.getField().getType().equals(BigDecimal.class)) {
                                val = new BigDecimal(String.valueOf(val));
                            }
                        } else if (Date.class.isAssignableFrom(excelFieldEntity.getField().getType())) {  //如果类属性是日期类型
                            if (val instanceof String) {
                                val = ExcelUtils.parseDate(val.toString(),excelFieldEntity.getPattern());
                            } else if (val instanceof Date) {
                                val = (Date) val;
                                if (excelFieldEntity.getField().getType().equals(Timestamp.class)) {
                                    val = new Timestamp(((Date) val).getTime());
                                }
                            } else {
                                rowErrorMsg.append(excelFieldEntity.getTitle() + ":要求是日期类型");
                            }
                        } else if (excelFieldEntity.getField().getType().equals(Boolean.class)) {          //如果类属性是布尔类型
                            if (val instanceof Boolean) {
                                val = (Boolean) val;
                            } else {
                                rowErrorMsg.append(excelFieldEntity.getTitle() + ":要求是布尔类型");
                            }
                        }
                        // 写入方法调用
                        excelFieldEntity.getField().set(newObj,val);
                    }else {
                        /**判断是否有默认值*/
                        if (excelFieldEntity.getRequired()) {
                            rowErrorMsg.append(excelFieldEntity.getTitle() + "数据必填,");
                            continue;
                        }
                    }
                    if (excelFieldEntity.getExcelVaildateEntity() != null) {
                        String message = ExcelValidateFieldUtil.validateField(excelFieldEntity, val, newObj);
                        if(StringUtils.isNotEmpty(message)){
                            rowErrorMsg.append(excelFieldEntity.getTitle()+":"+message);
                        }
                    }
                }
                if (rowErrorMsg.length() > 0) {
                    errorMsgList.add(new ValidateMessage((i+1),rowErrorMsg.toString()));
                }
                objList.add(newObj);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ExcelHandleException("EXCEL读取失败！");
        }
        return errorMsgList;
    }

}
